import java.util.concurrent.Semaphore;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import buffer.Buffer;
import buffer.FIFO;

public class ProducerConsumerProblem {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new Thread(ServiceLocator.getProducer(), "P").start();
		new Thread(ServiceLocator.getConsumer(), "C").start();
	}

}

class Consumer implements Runnable {

	private static Log log = LogFactory.getLog(Consumer.class.getName());

	private Buffer<String> buffer;

	public Consumer(Buffer<String> buffer) {
		this.buffer = buffer;
	}

	@Override
	public void run() {
		String line;

		do {
			
			while (buffer.isEmpty()) {
				try {
					synchronized (ServiceLocator.empty) {
						log.debug("buffer is empty, waiting...");
						ServiceLocator.empty.wait();
						log.debug("buffer is not empty, notified...");
					}
				} catch (InterruptedException ex) {
					
				}
			}
			
			line = buffer.get();

			// let producer starbe on resources
			try {
				Thread.sleep(10); 
			} catch (InterruptedException ex) {
				
			}			
			
			synchronized (ServiceLocator.full) {
				ServiceLocator.full.notifyAll();
			}
			
			System.out.println(line);
		} while (!line.equals("."));
	}
}

class Producer implements Runnable {
	private static Log log = LogFactory.getLog(Producer.class.getName());

	private Buffer<String> buffer;

	public Producer(Buffer<String> buffer) {
		this.buffer = buffer;
	}

	@Override
	public void run() {
		// for (String line : Text.text) {
		int i = 0;
		while (true) {

			i++;

			while (buffer.isFull()) {
				try {
					synchronized (ServiceLocator.full) {
						log.debug("buffer is full, waiting...");
						ServiceLocator.full.wait();
						log.debug("buffer is not full, notified...");
					}
				} catch (InterruptedException ex) {
					
				}
			}
			
			buffer.put("[ " + i + " ]");
			
			synchronized (ServiceLocator.empty) {
				ServiceLocator.empty.notifyAll();
			}
		}
	}
}

class Text {

	public static final String[] text = { "Хотіла б я піснею стати",
			"У сюю хвилину ясну,", "Щоб вільно по світі літати,",
			"Щоб вітер розносив луну.", "Щоб геть аж під яснії зорі",
			"Полинути співом дзвінким,", "Упасти на хвилі прозорі,",
			"Буяти над морем хибким.", "Лунали б тоді мої мрії",
			"І щастя моє таємне,", "Ясніші, ніж зорі яснії,",
			"Гучніші, ніж море гучне. ", "." };

}

class ServiceLocator {
	private static int BUFFER_SIZE = 4;
	private static Buffer<String> buffer = new FIFO<String>(BUFFER_SIZE);
	private static Producer producer;
	private static Consumer consumer;
	

	public static Object full = new String("full");
	public static Object empty = new String("empty");

	public static Producer getProducer() {
		if (producer == null) {
			producer = new Producer(buffer);
		}
		return producer;
	}

	public static Consumer getConsumer() {
		if (consumer == null) {
			consumer = new Consumer(buffer);
		}
		return consumer;
	}
}